#include "jugador.h"
#include<iostream>
#include<cmath>

Jugador::Jugador(pthread_mutex_t *NL, pthread_mutex_t *VIS, pthread_cond_t *VIS_NUE, pthread_mutex_t *EST, pthread_mutex_t *VEL, pthread_mutex_t *CIC, pthread_cond_t *ENVIO, pthread_mutex_t *ANG, string EQUIPO)
{

    nl=NL;
    vis=VIS;
    vista_nueva=VIS_NUE;
    est=EST;
    vel=VEL;
    cic=CIC;
    envio=ENVIO;
    ang=ANG;
    ciclo=0;
    ciclo_vista=0;
    ciclo_giro=0;
    ancho_vista=1;
    estado=0;  //Por defecto empezamos en before kick off
    angulo=0;
    equipo=EQUIPO;

}



int Jugador::girar(int grad)
{
   pthread_mutex_lock(vel);
   float coef=(1+5*velocidad);
   pthread_mutex_unlock(vel);
   int moment=grad*coef;
   int resto =0;

   if(moment>180)
   {
       resto=(moment-180)/coef;
       moment=180;
   }

   if(moment<(-180))
   {
       resto=(moment+180)/coef;
       moment=-180;

   }


   pthread_mutex_lock(ang);
   angulo=angulo+(grad-resto);
   pthread_mutex_unlock(ang);
   char buffer[50];
   sprintf (buffer, "(turn %d)", moment);
   pthread_mutex_lock(cic);
   pthread_cond_wait(envio,cic);
   jug.enviar(buffer);
   pthread_mutex_unlock(cic);
   return resto;
}


void Jugador::correr(int alfa){
    char buffer[50];
    if (alfa==0) alfa=1;
    sprintf (buffer, "(dash %d)", alfa);
    pthread_mutex_lock(cic);
    pthread_cond_wait(envio,cic);
    jug.enviar(buffer);
    pthread_mutex_unlock(cic);
}

void Jugador::conectar(int port, char* host, bool portero){
    jug.conexion(port, host);
    string mensaje;
    if(portero==1) mensaje="(init "+equipo+" (goalie))";
    else mensaje="(init "+equipo+")";
    char cad[500];
    strcpy(cad,mensaje.c_str());
    jug.enviar(cad);
}


void Jugador::desconectar(){
    jug.enviar("(bye)");
}

void Jugador::mover(){
   char buffer[50];
   sprintf (buffer, "(move %d %d)", posicion_x, posicion_y);
   jug.enviar(buffer);
}
void Jugador::mover(int x,int y){
   char buffer[50];
   sprintf (buffer, "(move %d %d)", x, y);
   jug.enviar(buffer);
}

void Jugador::chutar(int fuerza, float direccion){
   char buffer[50];
   sprintf (buffer, "(kick %d %f)", fuerza, direccion);
   pthread_mutex_lock(cic);
   pthread_cond_wait(envio,cic);
   jug.enviar(buffer);
   pthread_mutex_unlock(cic);
   cout<<"chuto"<<endl;
}

void Jugador::atrapar(float direccion){
   char buffer[50];
   sprintf (buffer, "(catch %f)", direccion);
   pthread_mutex_lock(cic);
   pthread_cond_wait(envio,cic);
   jug.enviar(buffer);
   pthread_mutex_unlock(cic);
}
void Jugador::setposicion(int x, int y){
   posicion_x=x;
   posicion_y=y;
}

void Jugador::getbalon(){
    cout<<"\n\n---GETBALL---\n\n";
    char cadena [500];
    int i=0,n=0,k=0;
    int espacios;
    char numero[8];
    int found;


    strcpy(cadena,jug.recibir());
    string str(cadena);

    cout<<"MENSAJE: "<<cadena;

    found=str.find("ball");
    cout<<"\nfound: "<<found<<endl;
    if(found!=-1)
    {
                for(i=found+6, n=0, k=0, espacios=0; espacios<4; i++,n++)
                {
                    numero[n]=cadena[i];
                    if(cadena[i]==32||cadena[i]==')')
                    {
                        BALL[k]=atof(numero);
                        cout<<"\nParametro"<<k+1<<" = "<<BALL[k];
                        k++;
                        n=-1;
                        espacios++;
                        bzero(numero, 8);


                    }
                }
    }else cout<<"no ball";


    bzero(cadena,500);

}

void Jugador::mostrar()
{
    char cadena [2048];

    for (int i=0;i<3;i++)
    {
        strcpy(cadena,jug.recibir());
        string str(cadena);
        cout<<cadena<<endl;
    }


}

void Jugador::guardar()
{
      char cadena [2048];
      strcpy(cadena,jug.recibir());
      string str(cadena);
      int ciclo_nuevo;
      Marca borde;
      switch (parser.seleccion(str))
      {
      case 1: //inicio
          cout<<"inicio"<<endl;
          pthread_mutex_lock(nl);
              parser.iniciar(str,&numero, &lado);
          pthread_mutex_unlock(nl);
          pthread_mutex_lock(est);
              estado=parser.getMensajeArbitro(cadena);
          pthread_mutex_unlock(est);
          cout<<"numero:"<<numero<<"   "<<"lado:"<<lado<<endl;
          break;
      case 2:  //reconexion
          break; // De momento, no podemos reconectar, así que no se va a dar este caso
      case 3://error
          break;  //de momento no tenemos gestion de errores
      case 4:   //arbitro
          cout<<"arbitro"<<endl;
          pthread_mutex_lock(est);
                estado=parser.getMensajeArbitro(cadena);
          pthread_mutex_unlock(est);
          cout<<"dice "<<str<<endl;
          break;
      case 5: //vista
          pthread_mutex_lock(vis);
          pthread_mutex_lock(nl);
          if(lado=='l')
          {
              if(vista!=str)
              {
                vista=str;
                pthread_cond_signal(vista_nueva);
              }
          }
          else
          {
              if(vista!=cambioCampo(str))
              {
                  vista=cambioCampo(str);
                  pthread_cond_signal(vista_nueva);
              }
          }
          pthread_mutex_unlock(nl);
          pthread_mutex_unlock(vis);
          if (ciclo_vista!=parser.ciclo(str));
          {
              ciclo_vista=parser.ciclo(str);
              if(parser.veo(str,"line"))
              {
                if(parser.veo(str,"line b",&borde))
                {
                    if (borde.ang<0)
                    {
                      pthread_mutex_lock(ang);
                      angulo=((-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                    else
                    {
                      pthread_mutex_lock(ang);
                      angulo=((180-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                }
                else if(parser.veo(str,"line t",&borde))
                {
                    if (borde.ang<0)
                    {
                      pthread_mutex_lock(ang);
                      angulo=((180-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                    else
                    {
                      pthread_mutex_lock(ang);
                      angulo=((360-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                }
                if(parser.veo(str,"line l",&borde))
                {
                    if (borde.ang<0)
                    {
                      pthread_mutex_lock(ang);
                      angulo=((90-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                    else
                    {
                      pthread_mutex_lock(ang);
                      angulo=((270-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                }
                else if(parser.veo(str,"line r",&borde))
                {
                    if (borde.ang<0)
                    {
                      pthread_mutex_lock(ang);
                      angulo=((270-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                    else
                    {
                      pthread_mutex_lock(ang);
                      angulo=((90-borde.ang)+angulo)/2;
                      pthread_mutex_unlock(ang);
                    }
                }
            }
            pthread_mutex_lock(ang);
            pthread_mutex_unlock(ang);
          }
          break;
      case 6://oido
          break; //de momento solo escuchamos al arbitro
      case 7://estado fisico
          pthread_mutex_lock(vel);
          ciclo_nuevo=parser.fisico(str,&velocidad);
          pthread_mutex_unlock(vel);
          pthread_mutex_lock(cic);
          if (ciclo_nuevo!=ciclo)
          {
              ciclo=ciclo_nuevo;
              pthread_cond_signal(envio);
          }
          pthread_mutex_unlock(cic);
          break;

      default:
          break;
      }
}

int Jugador::getEstado()
{
    pthread_mutex_lock(est);
    int x=estado;
    pthread_mutex_unlock(est);
    return x;

}

void Jugador::correrDentro(int f)
{

    Marca borde;
    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    pthread_mutex_lock(cic);
    int ciclo_cache=ciclo;
    pthread_mutex_unlock(cic);
    int angulo_temp;

    if (parser.veo(cache,"line",&borde)&&borde.dist<10)
    {
        if((ciclo_giro+3)<ciclo_cache)// Evita que gire otra vez con la misma vista
        {
            ciclo_giro=ciclo_cache;
            angulo_temp=borde.ang;
            do
            {
            angulo_temp=girar(angulo_temp);
            }
            while(angulo_temp>1||angulo_temp<-1);
        }
    }
    else 
        correr(f);
}

bool Jugador::buscarBalon(bool sentido)
{
    pthread_mutex_lock(vis);
    pthread_cond_wait(vista_nueva,vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    int s;
    if (sentido==0) s=1;
    if (sentido==1) s=-1;
    Marca balon;
    if(!parser.veo(cache,"ball",&balon))
    {
        girar(20*s);
        return 0;
    }
    else girar(balon.ang);
    return 1;

}

float Jugador::perseguirBalon()
{
    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    Marca balon;
    int f=100;
    if(!parser.veo(cache,"ball",&balon))
        return -1;
    else
    {
        if(abs(balon.ang)>1)//un pequeño margen por los errores de medida, si no, gira muchos ciclos apenas nada
            girar(balon.ang);
        if(balon.dist>0.4)//Si esta cerca no necesita acelerar para llegar al balon
        {

            if(balon.dist<10)
            {
                pthread_mutex_lock(vel);
                float vel_cache=velocidad;
                pthread_mutex_unlock(vel);
                float diferencia=velocidadRelativa(cache)-vel_cache;
                if(abs(diferencia)>vel_cache*0.2&&vel_cache>0.2)//solo frena si va mucho mas rápido que el balon
                {
                    /*if(vel_cache<0.25)//si va despacio, acelera un poco para llegar
                        f=20;
                    else                //si va mas rápido, no acelera, para no pasarse
                        f=-20;*/
                    f=100-100*vel_cache*0.3*(10-balon.dist);
                }
                else if(balon.dist<2)//si está muy cerca tampoco puede acelerar al máximo
                    f=50*balon.dist;
            }
            correr(f);
            //localizarCompanero(f);
        }

    }
    return balon.dist;
}

Marca Jugador::vigilar()
{
    //cout<<"---VIGILAR---";

    bool sentido=0;
    string cache;
    Marca balon;
    pthread_mutex_lock(vis);
    cache=vista;
    pthread_mutex_unlock(vis);

    while(!parser.veo(cache,"ball"))
    {
        pthread_mutex_lock(vis);
        cache=vista;
        pthread_mutex_unlock(vis);
        if(!parser.veo(cache,"ball"))
        {
           if(parser.veo(cache,"flag g l t")) sentido=1;
           if(parser.veo(cache,"flag g l b")) sentido=0;
           if(sentido==0){ girar(-25); }
           if(sentido==1){ girar(25); }
        }
    }

    if(parser.veo(cache,"ball"))
    {
        parser.veo(cache,"ball",&balon);
        while(abs(balon.ang)>5)
        {
            girar(balon.ang/4); //Solo la mitad para controlarlo mejor
            pthread_mutex_lock(vis);
            cache=vista;
            pthread_mutex_unlock(vis);
            parser.veo(cache,"ball",&balon);
        }
    }
    //cout<<"\nVDistancia: "<<balon.dist<<"VAngulo: "<<balon.ang<<endl;
    if(!parser.veo(cache,"ball")) balon.dist=80;
    return balon;
}


int Jugador::recepcion(bool lado)  //lado=0 izquierda
{                                  //lado=1 derecha
    int info;
    orientar(lado);
    int sentido;
    if(lado==0) sentido=1;
    if(lado==1) sentido=-1;
    girarCabeza(180*sentido);
    info=interceptar(lado);
    girarCabeza(-90*sentido);
    return info;

}

int Jugador::interceptar(bool lado) //Solo debe utilizarse con el portero, dentro de recepcion
{
    string cache;
    Marca balon;
    bool ok=0;
    int salida=0;
    int sentido;
    if(lado==0) sentido=1;
    if(lado==1) sentido=-1;
    do
    {
        ok=0;
        pthread_mutex_lock(vis);
        cache=vista;
        pthread_mutex_unlock(vis);
        if(parser.veo(cache,"ball"))
        {
            parser.veo(cache,"ball",&balon);
            correr(-balon.ang*10*sentido);
            cout<<"\n\nDistancia: "<<balon.dist<<"\nAngulo: "<<balon.ang;

            if(balon.dist>50)  //El balon se ha alejado
            {
                salida=-1;
                ok=1;
            }
            if(balon.dist<10&&balon.dist!=0)//Este valor hay que bajarlo con pruebas
            {
                salida=1;  //El balon esta muy cerca (puede atraparse)
                ok=1;
            }
        }
    }
    while(!ok);
    return salida;
}

int Jugador::orientar(bool dir) //dir=0 izquierda
{                               //dir=1 derecha
    Marca line;
    string objetivo;
    string cache;
    bool ok=0;
    int sentido;
    if(dir==0)
    { sentido=1; objetivo="line t";}
    if(dir==1)
    { sentido=-1; objetivo="line b";}
    do
    {
        pthread_mutex_lock(vis);
        cache=vista;
        pthread_mutex_unlock(vis);
        if(!parser.veo(cache,objetivo))
        {
           girar(-20*sentido);
        }
        else
        {
            parser.veo(cache,objetivo,&line);
            if(abs(line.ang)>30)
            {
                 if(line.ang<0&&line.ang>-88) girar(1);
                 if(line.ang>0&&line.ang<88) girar(-1);
                 if(line.ang<-88||line.ang>88) ok=1;
             }
        }
     }while(!ok);
}

void Jugador::girarCabeza(int angulo)
{
    char buffer[50];
    sprintf (buffer, "(turn_neck %d)", angulo);
    cout<<"enviamos: "<<buffer;
    jug.enviar(buffer);
}

void Jugador::anchoVista(int a)
{
    char buffer[50];
    if (a==0&&a!=ancho_vista)
    {
        ancho_vista=a;
        cout<<"vista estrecha"<<endl;
        sprintf (buffer, "(change_view narrow high)");
        jug.enviar(buffer);
    }
    else if(a==1&&a!=ancho_vista)
    {
        ancho_vista=1;
        cout<<"vista normal"<<endl;
        sprintf (buffer, "(change_view normal high)");
        jug.enviar(buffer);
    }

}

float Jugador::velocidadRelativa(string cache)
{
    char str[2048];
    strcpy(str, cache.c_str());
    /*pthread_mutex_lock(vel);
    cout<<"veloci: "<<velocidad<<endl;
    pthread_mutex_unlock(vel);*/
    BalonParams x=parser.balon(str);
    pthread_mutex_lock(ang);
    int a0=angulo;
    pthread_mutex_unlock(ang);
    float Vx=x.Velocidad[0]*cos((x.Angulo*(3.14159/180))+a0)-x.Velocidad[1]*(3.14159/180)*sin((x.Angulo*(3.14159/180))+a0);
    float Vy=-(x.Velocidad[0]*sin((x.Angulo*(3.14159/180))+a0)+x.Velocidad[1]*(3.14159/180)*cos((x.Angulo*(3.14159/180))+a0));
   /* cout<<"modulo: "<<sqrt(pow(Vx,2)+pow(Vy,2))<<endl;
    cout<<"Argumento: "<<a0+atan(Vy/Vx)*(180/3.14159)<<endl;
    cout<<"Vx= "<<Vx<<endl;
    cout<<"Vy= "<<Vy<<endl<<endl;*/
    return sqrt(pow(Vx,2)+pow(Vy,2));
}

void Jugador::posicionInicial(bool portero)
{
    pthread_mutex_lock(nl);
    int dorsal=numero;
    pthread_mutex_unlock(nl);
    if(portero==1)
        mover(-52,0);
    else
    switch (dorsal)
    {
    case 1:
        setposicion(-5,-15);
        mover();
        break;
    case 2:
        setposicion(-10,0);
        mover();
        break;
    case 3:
        setposicion(-5,15);
        mover();
        break;
    case 4:
        setposicion(-20,-25);
        mover();
        break;
    case 5:
        setposicion(-20,-10);
        mover();
        break;
    case 6:
        setposicion(-20,10);
        mover();
        break;
    case 7:
        setposicion(-20,25);
        mover();
        break;
    case 8:
        setposicion(-25,-15);
        mover();
        break;
    case 9:
        setposicion(-25,0);
        mover();
        break;
    case 10:
        setposicion(-25,15);
        mover();
        break;
    case 11:
        setposicion(-52,0);
        mover();
        break;
    }
}

void Jugador::parar()
{
    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    Marca balon;
    parser.veo(cache,"ball",&balon);

    if(parser.veo(cache,"ball",&balon)&&balon.dist<2)
    {
        pthread_mutex_lock(vis);
        cache=vista;
        pthread_mutex_unlock(vis);
        parser.veo(cache,"ball",&balon);
        cout<<"atrapar en: "<<balon.ang;
        atrapar(balon.ang);
    }
}

void Jugador::tiroPuerta()
{

    string cache;
    Marca poste_t;
    Marca poste_b;
    Marca portero;
    Marca porteria;

        pthread_mutex_lock(vis);
        pthread_cond_wait(vista_nueva,vis);//Esperamos a una vista nueva para que los ángulos sean correctos
        cache=vista;
        pthread_mutex_unlock(vis);
        parser.veo(cache,"flag g r t",&poste_t);
        parser.veo(cache,"flag g r b",&poste_b);

        if(parser.veo(cache,"goal r",&porteria))//Veo la portería?
        {
            if(!parser.veo(cache,"goalie",&portero))//Si no hay portero, tiramos al centro
                chutar(100,porteria.ang);
            else
                if((abs(poste_t.ang)+abs(portero.ang))>(abs(poste_b.ang)+abs(portero.ang)))//chuta hacia el lado que le va peor al portero
                    chutar(100,(poste_t.ang/0.9));
                else
                    chutar(100,(poste_b.ang/0.9));

        }
}

string Jugador::cambioCampo(string cad)
{
    string::iterator it;
    for(it=(cad.begin()+1);it<(cad.end()-1);it++)
    {
        if(*it=='l'&&(*(it+1)==' '||*(it+1)==')')&&*(it-1)==' ')
            *it='r';
        else if(*it=='r'&&(*(it+1)==' '||*(it+1)==')')&&*(it-1)==' ')
            *it='l';
        else if(*it=='t'&&(*(it+1)==' '||*(it+1)==')')&&*(it-1)==' ')
            *it='b';
        else if(*it=='b'&&(*(it+1)==' '||*(it+1)==')')&&*(it-1)==' ')
            *it='t';
    }
    return cad;
}

char Jugador::getLado()
{
 pthread_mutex_lock(nl);
 char x=lado;
 pthread_mutex_unlock(nl);
 return x;
}

void Jugador::jugar()
{
    int dorsal;
    pthread_mutex_lock(nl);
    dorsal=numero;
    pthread_mutex_unlock(nl);
    int distancia;
    int modo;
    string cache;
    while(1)
    {
        modo=getEstado();
        if(modo==0||modo==22||modo==23)//Before_kick_off, goal_l o goal_r
        {
        //Nos colocamos en posición
            posicionInicial();
            while(getEstado()==0||getEstado()==22||getEstado()==23);//lo hace una vez y espera
        }
        if(modo==1)//play_on
        {
        //Juego normal
            juegoNormalAlex();

        }
        if((modo==2&&getLado()=='l')||(modo==3&&getLado()=='r'))//corner_kick sacamos nosotros
        {
            if(dorsal==8||dorsal==10)
                saque();
            else
                while(!buscarBalon());
        }
        if((modo==2&&getLado()=='r')||(modo==3&&getLado()=='l'))//corner_kick sacan ellos
        {
            while(!buscarBalon());
        }
        if(modo==4)//drop_ball
        {

        }
        if(modo==5)//offside_l
        {

        }
        if(modo==6)//offside_r
        {

        }
        if(modo==7)//half_time
        {

        }
        if(modo==8)//time_over
        {

        }
        if(modo==9)//time_up_whithout_a_team
        {

        }
        if(modo==10)//time_up
        {

        }
        if(modo==11)//time_extended
        {

        }
        if((modo==12&&getLado()=='l')||(modo==13&&getLado()=='r'))//kick_off_l y somos l o kick_off_r y somos r
        {
        //saque desde el centro del campo(sacamos nosotros)
            if(dorsal==2)
            {
                saque();
            }
            else
                while(!buscarBalon());


        }
        if((modo==12&&getLado()=='r')||(modo==13&&getLado()=='l'))//kick_off_r y somos l o al reves
        {
            while(!buscarBalon());
        }
        if((modo==14&&getLado()=='l')||(modo==15&&getLado()=='r'))//kick_in sacamos nosotros
        {
            while(!buscarBalon());
            pthread_mutex_lock(vis);
            pthread_cond_wait(vista_nueva,vis);
            cache=vista;
            pthread_mutex_unlock(vis);
            //primero busca el balón, luego solo va si es un jugador de esa banda
            if((dorsal==8||dorsal==4||dorsal==1)&&parser.veo(cache,"(line t)"))//si ve line t, es que el balon esta en ella
                saque();
            else if(dorsal==10||dorsal==6||dorsal==3)//si no ve line t, está en line b
                saque();

        }
        if((modo==15&&getLado()=='l')||(modo==14&&getLado()=='r'))//kick_in sacan ellos
        {
            while(!buscarBalon());

        }
        if((modo==16&&getLado()=='l')||(modo==17&&getLado()=='r'))//free_kick sacamos nosotros
        {
            while(!buscarBalon());
            pthread_mutex_lock(vis);
            pthread_cond_wait(vista_nueva,vis);
            cache=vista;
            pthread_mutex_unlock(vis);
            if(dorsal==5)//falta pongo que saque siempre el 5, por que evaluar el mas cercano no podemos
                saque();

        }
        if((modo==17&&getLado()=='l')||(modo==16&&getLado()=='r'))//free_kick sacan ellos
        {
            while(!buscarBalon());
        }
        if(modo==18)//foul_l
        {

        }
        if(modo==19)//foul_r
        {

        }
        if((modo==20&&getLado()=='l')||(modo==21&&getLado()=='r'))//goal_kick y sacamos
        {
            if(dorsal==11)
                saque();
        }
        if((modo==21&&getLado()=='l')||(modo==20&&getLado()=='r'))//goal_kick y sacan
        {
            while(!buscarBalon());
        }
        if(modo==24)//goalie_catch_ball_l
        {

        }
        if(modo==25)//goalie_catch_ball_r
        {

        }

    }
}

void Jugador::saque()
{
    Marca amigo;
    int distancia=perseguirBalon();
    if(distancia==-1)
    {
        buscarBalon();
    }

    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    Marca test;
    if(parser.veo(cache,"ball",&test))
        cout<<"ball "<<test.dist<<"  "<<test.ang<<endl;
    if(parser.veo(cache,"flag c",&test))
        cout<<"ball "<<test.dist<<"  "<<test.ang<<endl;

    if(distancia<0.4&&distancia!=-1)
    {
       while(!parser.veo(cache,equipo,&amigo))
        {
           girar(20);
           pthread_mutex_lock(vis);
           pthread_cond_wait(vista_nueva,vis);
           cache=vista;
           pthread_mutex_unlock(vis);
       }


           chutar(50,amigo.ang);

    }
}
void Jugador::juegoNormal()
{
    int distancia=perseguirBalon();
    if(distancia==-1)
    {
        buscarBalon();
    }

    if(distancia<0.1&&distancia!=-1)
        //chutar(100,0);
        tiroPuerta();

}

void Jugador::jugarPortero()
{
    Marca balon;
    int info=0;
    int modo;
    int accion=0;
    do
    {
        modo=getEstado();
        if(modo==16) saque();
        else
        {
            do
            {
                switch (accion)
                {
                case 0:
                    balon=vigilar();
                    if(balon.dist>50) accion=0;
                    if(balon.dist<50&&balon.dist>15)
                    {
                        if(balon.ang<0) accion=1;
                        if(balon.ang>0) accion=2;
                    }
                    if(balon.dist<10) accion=5;
                    break;
                case 1:
                    info=recepcion(0);
                    if(info==-1) accion=0;
                    if(info==1) accion=3; //encarar
                    break;
                case 2:
                    info=recepcion(1);
                    if(info==-1) accion=0;
                    if(info==1) accion=4; //encarar
                    break;
                case 3:
                    buscarBalon(1);
                    accion=5;
                    break;
                case 4:
                    buscarBalon(0);
                    accion=5;
                    break;
                case 5:
                    perseguirBalon();
                    parar();
                    accion=0;
                    break;
                case 6:

                    break;
                }
            modo=getEstado();
            }
            while(modo!=16);
        }
    }
    while(1);
}

void Jugador::zonas()
{
    int dorsal;
    pthread_mutex_lock(nl);
    dorsal=numero;
    pthread_mutex_unlock(nl);
    limite_b=0;
    limite_t=0;
    limite_l=0;
    limite_r=0;
    if(dorsal==1||dorsal==8)
        limite_b=42;
    else if(dorsal==4)
        limite_b=50;
    else if(dorsal==2||dorsal==9)
    {
        limite_b=21;
        limite_t=21;
    }
    else if(dorsal==5)
    {
        limite_b=32;
        limite_t=15;
    }
    else if(dorsal==6)
    {
        limite_b=15;
        limite_t=32;
    }
    else if(dorsal==3||dorsal==10)
        limite_t=42;
    else if(dorsal==7)
        limite_t=50;
    if(dorsal==3||dorsal==2||dorsal==1)
        limite_r=50;
    else if(dorsal==7||dorsal==6||dorsal==5||dorsal==4)
    {
        limite_r=20;
        limite_l=20;
    }
    else if(dorsal==10||dorsal==9||dorsal==8)
        limite_l=50;
}
bool Jugador::correrZona(int f)
{
    pthread_mutex_lock(vis);
    pthread_cond_wait(vista_nueva,vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    pthread_mutex_lock(ang);
    int a=angulo;
    pthread_mutex_unlock(ang);
    Marca borde;
    bool enable=1;
    if(parser.veo(cache,"line t",&borde)&&borde.dist<limite_t)
        enable=0;
    if(parser.veo(cache,"line b",&borde)&&borde.dist<limite_b)
        enable=0;
    if(parser.veo(cache,"line r",&borde)&&borde.dist<limite_l)
        enable=0;
    if(parser.veo(cache,"line l",&borde)&&borde.dist<limite_r)
        enable=0;
    if(parser.veo(cache,equipo,&borde)&&borde.dist<10)
        enable=0;
    if(enable==1)
        correr(f);
    return enable;

}

void Jugador::juegoNormalAlex()
{
    string cache;
    int distancia=perseguirBalonAlex();
    if(distancia==-1)
    {
        buscarBalon();
    }

    if(distancia<0.1&&distancia!=-1)
    {
        pthread_mutex_lock(vis);
        pthread_cond_wait(vista_nueva,vis);
        cache=vista;
        pthread_mutex_unlock(vis);
        pthread_mutex_lock(ang);
        int a=angulo;
        pthread_mutex_unlock(ang);
        Marca objeto;
        //if(parser.veo(cache,"goal r",&objeto)&&objeto.dist<25)//ve la portería y esta cerca, tira
            tiroPuerta();
        /*else */if(abs(a)<45&&parser.veo(cache,equipo,&objeto))//si mira hacia delante y ve un compañero, pasa
            chutar(5*objeto.dist,objeto.ang);
        else if(abs(a)<180&&parser.veo(cache,equipo,&objeto))//si mira a los lados, lo mismo
            chutar(5*objeto.dist,objeto.ang);
        else if(parser.veo(cache,"goal r"))//si no, tira hacia la porteria rival
                tiroPuerta();
        else //si no, gira y vuelta a empezar
            girar(20);




    }
 }



float Jugador::perseguirBalonAlex()
{
    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);
    Marca balon;
    int f=100;
    if(!parser.veo(cache,"ball",&balon))
        return -1;
    else
    {
        if(abs(balon.ang)>1)//un pequeño margen por los errores de medida, si no, gira muchos ciclos apenas nada
            girar(balon.ang);
        if(balon.dist>0.4)//Si esta cerca no necesita acelerar para llegar al balon
        {

            if(balon.dist<10)
            {
                pthread_mutex_lock(vel);
                float vel_cache=velocidad;
                pthread_mutex_unlock(vel);
                float diferencia=velocidadRelativa(cache)-vel_cache;
                if(abs(diferencia)>vel_cache*0.2&&vel_cache>0.2)//solo frena si va mucho mas rápido que el balon
                {
                    /*if(vel_cache<0.25)//si va despacio, acelera un poco para llegar
                        f=20;
                    else                //si va mas rápido, no acelera, para no pasarse
                        f=-20;*/
                    f=100-100*vel_cache*0.3*(10-balon.dist);
                }
                else if(balon.dist<2)//si está muy cerca tampoco puede acelerar al máximo
                    f=50*balon.dist;
            }
            correrZona(f);
            //localizarCompanero(f);
        }

    }
    
    return balon.dist;
}

void Jugador::localizarCompanero(float f, Marca ball){

    pthread_mutex_lock(vis);
    string cache=vista;
    pthread_mutex_unlock(vis);

    char str[2048];

    strcpy(str, cache.c_str());

    JugadorParams jug =parser.jugadores(str, equipo);

    int vel;

    cout<<"angulo jugador: "<<jug.Angulo<<endl;
    cout<<"jug.dist "<<jug.Distancia<<endl;
    cout<<"angulo balon: "<<ball.ang<<endl;
    cout<<"ball.dist "<<ball.dist<<endl;

       if(abs(jug.Distancia-ball.dist)>=ball.dist){
        if(abs(jug.Angulo-ball.ang)<10){
            vel=f*0.55;
            correrDentro(vel);
        }
        else{
            correrDentro(f);
        }
    }
    else{
        correrDentro(f);
    }

}

